/*
 * Copyright (C) 2024 Huawei Device Co., Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

import Log from './Log';
import marsnapi from 'libmarsnapi.so';

class Xlog implements Log.LogImp {

  public static readonly LEVEL_ALL: number = 0;
  public static readonly LEVEL_VERBOSE: number = 0;
  public static readonly LEVEL_DEBUG: number = 1;
  public static readonly LEVEL_INFO: number = 2;
  public static readonly LEVEL_WARNING: number = 3;
  public static readonly LEVEL_ERROR: number = 4;
  public static readonly LEVEL_FATAL: number = 5;
  public static readonly LEVEL_NONE: number = 6;
  public static readonly COMPRESS_LEVEL1: number = 1;
  public static readonly COMPRESS_LEVEL2: number = 2;
  public static readonly COMPRESS_LEVEL3: number = 3;
  public static readonly COMPRESS_LEVEL4: number = 4;
  public static readonly COMPRESS_LEVEL5: number = 5;
  public static readonly COMPRESS_LEVEL6: number = 6;
  public static readonly COMPRESS_LEVEL7: number = 7;
  public static readonly COMPRESS_LEVEL8: number = 8;
  public static readonly COMPRESS_LEVEL9: number = 9;
  public static readonly AppednerModeAsync: number = 0;
  public static readonly AppednerModeSync: number = 1;
  public static readonly ZLIB_MODE: number = 0;
  public static readonly ZSTD_MODE: number = 1;

  static XLoggerInfo = class {
    public level: number;
    public tag: string;
    public filename: string;
    public funcname: string;
    public line: number;
    public pid: number;
    public tid: number;
    public maintid: number;
  }

  public static XLogConfig = class {
    public level: number = Xlog.LEVEL_INFO;
    public mode: number = Xlog.AppednerModeAsync;
    public logdir: string = "";
    public nameprefix: string = "";
    public pubkey: string = "";
    public compressmode: number = Xlog.ZLIB_MODE;
    public compresslevel: number = 0;
    public cachedir: string = "";
    public cachedays: number = 0;

    public constructor(level?: number, mode?: number, logdir?: string, nameprefix?: string, pubkey?: string, compressmode?: number, compresslevel?: number, cachedir?: string, cachedays?: number) {
      this.level = level;
      this.mode = mode;
      this.logdir = logdir;
      this.nameprefix = nameprefix;
      this.pubkey = pubkey;
      this.compressmode = compressmode;
      this.compresslevel = compresslevel;
      this.cachedir = cachedir;
      this.cachedays = cachedays;
    }
  }

  public static open(isLoadLib: boolean, level: number, mode: number,
                     cacheDir: string, logDir: string, nameprefix: string, pubkey: string): void {
    /*if (isLoadLib) {
      System.loadLibrary("c++_shared");
      System.loadLibrary("marsxlog");
    }*/

    let logConfig: Xlog.XLogConfig = new Xlog.XLogConfig();
    logConfig.level = level;
    logConfig.mode = mode;
    logConfig.logdir = logDir;
    logConfig.nameprefix = nameprefix;
    logConfig.pubkey = pubkey;
    logConfig.compressmode = Xlog.ZLIB_MODE;
    logConfig.compresslevel = 0;
    logConfig.cachedir = cacheDir;
    logConfig.cachedays = 0;
    Xlog.native_appenderOpen(logConfig);
  }

  private static decryptTag(tag: string): string {
    return tag;
  }

  public logV(logInstancePtr: number, tag: string, filename: string, funcname: string,
              line: number, pid: number, tid: number, maintid: number, log: string): void {
    Xlog.native_logWrite2(logInstancePtr, Xlog.LEVEL_VERBOSE, Xlog.decryptTag(tag), filename, funcname, line, pid, tid, maintid, log);
  }

  public logD(logInstancePtr: number, tag: string, filename: string, funcname: string,
              line: number, pid: number, tid: number, maintid: number, log: string): void {
    Xlog.native_logWrite2(logInstancePtr, Xlog.LEVEL_DEBUG, Xlog.decryptTag(tag), filename, funcname, line, pid, tid, maintid, log);
  }

  public logI(logInstancePtr: number, tag: string, filename: string, funcname: string,
              line: number, pid: number, tid: number, maintid: number, log: string): void {
    Xlog.native_logWrite2(logInstancePtr, Xlog.LEVEL_INFO, Xlog.decryptTag(tag), filename, funcname, line, pid, tid, maintid, log);
  }

  public logW(logInstancePtr: number, tag: string, filename: string, funcname: string,
              line: number, pid: number, tid: number, maintid: number, log: string): void {
    Xlog.native_logWrite2(logInstancePtr, Xlog.LEVEL_WARNING, Xlog.decryptTag(tag), filename, funcname, line, pid, tid, maintid, log);
  }

  public logE(logInstancePtr: number, tag: string, filename: string, funcname: string,
              line: number, pid: number, tid: number, maintid: number, log: string): void {
    Xlog.native_logWrite2(logInstancePtr, Xlog.LEVEL_ERROR, Xlog.decryptTag(tag), filename, funcname, line, pid, tid, maintid, log);
  }

  public logF(logInstancePtr: number, tag: string, filename: string, funcname: string,
              line: number, pid: number, tid: number, maintid: number, log: string): void {
    Xlog.native_logWrite2(logInstancePtr, Xlog.LEVEL_ALL, Xlog.decryptTag(tag), filename, funcname, line, pid, tid, maintid, log);
  }

  public appenderOpen(level: number, mode: number, cacheDir: string, logDir: string, nameprefix: string, cacheDays: number): void {

    let logConfig: Xlog.XLogConfig = new Xlog.XLogConfig();
    logConfig.level = level;
    logConfig.mode = mode;
    logConfig.logdir = logDir;
    logConfig.nameprefix = nameprefix;
    logConfig.compressmode = Xlog.ZLIB_MODE;
    logConfig.pubkey = "";
    logConfig.cachedir = cacheDir;
    logConfig.cachedays = cacheDays;
    logConfig.compresslevel = 0;
    Xlog.native_appenderOpen(logConfig);
  }

  public static logWrite(logInfo: Xlog.XLoggerInfo, log: string) : any {
    console.log("native_logWrite")
    return marsnapi.Xlog_logWrite(logInfo, log);
  }

  public static logWrite2(level: number, tag: string, filename: string, funcname: string,
                          line: number, pid: number, tid: number, maintid: number, log: string): void {
    console.log("logWrite2")
    Xlog.native_logWrite2(0, level, tag, filename, funcname, line, pid, tid, maintid, log);
  }

  public static native_logWrite2(logInstancePtr: number, level: number, tag: string, filename: string, funcname: string,
                          line: number, pid: number, tid: number, maintid: number, log: string): any {
    console.log("native_logWrite2")
    let ret = marsnapi.Xlog_logWrite2(logInstancePtr, level, tag, filename, funcname, line, pid, tid, maintid, log);
    console.log("native_logWrite2 ret = " + ret)
    return ret
  }

  public setLogLevel(logInstancePtr: number): any {
    console.log("setLogLevel")
    return marsnapi.Xlog_setLogLevel(logInstancePtr);
  }

  public getLogLevel(logInstancePtr: number): any {
    console.log("getLogLevel")
    return marsnapi.Xlog_getLogLevel(logInstancePtr);
  }

  public setAppenderMode(logInstancePtr: number, mode: number): any {
    console.log("setAppenderMode");
    return marsnapi.Xlog_setAppenderMode(logInstancePtr, mode);
  }

  public openLogInstance(level: number, mode: number, cacheDir: string, logDir: string, nameprefix: string, cacheDays: number): number {
    let logConfig: Xlog.XLogConfig = new Xlog.XLogConfig();
    logConfig.level = level;
    logConfig.mode = mode;
    logConfig.logdir = logDir;
    logConfig.nameprefix = nameprefix;
    logConfig.compressmode = Xlog.ZLIB_MODE;
    logConfig.compresslevel = 0;
    logConfig.pubkey = "";
    logConfig.cachedir = cacheDir;
    logConfig.cachedays = cacheDays;
    return this.newXlogInstance(logConfig);
  }

  public getXlogInstance(nameprefix: string): any {
    console.log("native_getXlogInstance");
    return marsnapi.Xlog_getXlogInstance(nameprefix);
  }

  public releaseXlogInstance(nameprefix: string): any {
    console.log("native_releaseXlogInstance");
    return marsnapi.Xlog_releaseXlogInstance(nameprefix);
  }

  public newXlogInstance(logConfig: Xlog.XLogConfig): any {
    console.log("native_newXlogInstance");
    return marsnapi.Xlog_newXlogInstance(logConfig);
  }

  public setConsoleLogOpen(logInstancePtr: number, isOpen: boolean): any {
    console.log("native_setConsoleLogOpen");
    return marsnapi.Xlog_setConsoleLogOpen(logInstancePtr, isOpen);
  }

  private static native_appenderOpen(logConfig: Xlog.XLogConfig): any {
    return marsnapi.Xlog_appenderOpen(logConfig);
  }

  public appenderClose(): any {
    console.log("native_appenderClose")
    return marsnapi.Xlog_appenderClose();
  }

  public appenderFlush(logInstancePtr: number, isSync: boolean): any {
    console.log("native_appenderFlush");
    return marsnapi.Xlog_appenderFlush(logInstancePtr, isSync);
  }

  public setMaxFileSize(logInstancePtr: number, aliveSeconds: number): any {
    console.log("native_setMaxFileSize");
    return marsnapi.Xlog_setMaxFileSize(logInstancePtr, aliveSeconds);
  }

  public setMaxAliveTime(logInstancePtr: number, aliveSeconds: number): any {
    console.log("Xlog_setMaxAliveTime");
    return marsnapi.Xlog_setMaxAliveTime(logInstancePtr, aliveSeconds);
  }
}

namespace Xlog {
  export type XLoggerInfo = typeof Xlog.XLoggerInfo.prototype;

  export type XLogConfig = typeof Xlog.XLogConfig.prototype;
}
export default Xlog;